#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
RTSP延迟测试工具
用于诊断RTSP推流端和拉流端的延迟问题
"""

import subprocess
import time
import threading
import json
from datetime import datetime
import socket
import struct

class RTSPLatencyTester:
    def __init__(self, rtsp_url="rtsp://192.168.226.141:8554/camera_test"):
        self.rtsp_url = rtsp_url
        self.server_ip = "192.168.226.141"
        self.server_port = 8554
        self.results = {
            "network_latency": [],
            "rtsp_connection_time": [],
            "stream_info": {},
            "errors": []
        }
    
    def test_network_latency(self, count=10):
        """测试网络延迟"""
        print(f"🌐 测试网络延迟到 {self.server_ip}...")
        
        try:
            # Windows ping命令
            cmd = f"ping {self.server_ip} -n {count}"
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True, encoding='gbk')
            
            if result.returncode == 0:
                lines = result.stdout.split('\n')
                latencies = []
                
                for line in lines:
                    if "时间=" in line or "time=" in line:
                        try:
                            # 提取延迟时间
                            if "时间=" in line:
                                time_part = line.split("时间=")[1].split("ms")[0]
                            else:
                                time_part = line.split("time=")[1].split("ms")[0]
                            
                            if "<" in time_part:
                                latency = 1  # <1ms当作1ms
                            else:
                                latency = int(time_part)
                            latencies.append(latency)
                        except:
                            continue
                
                if latencies:
                    avg_latency = sum(latencies) / len(latencies)
                    min_latency = min(latencies)
                    max_latency = max(latencies)
                    
                    self.results["network_latency"] = {
                        "average": avg_latency,
                        "min": min_latency,
                        "max": max_latency,
                        "samples": latencies
                    }
                    
                    print(f"  ✅ 网络延迟 - 平均: {avg_latency:.1f}ms, 最小: {min_latency}ms, 最大: {max_latency}ms")
                    return avg_latency
            
        except Exception as e:
            error_msg = f"网络延迟测试失败: {str(e)}"
            print(f"  ❌ {error_msg}")
            self.results["errors"].append(error_msg)
        
        return None
    
    def test_rtsp_connection(self):
        """测试RTSP连接时间"""
        print(f"📹 测试RTSP连接时间...")
        
        try:
            start_time = time.time()
            
            # 尝试建立TCP连接到RTSP端口
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(10)  # 10秒超时
            
            result = sock.connect_ex((self.server_ip, self.server_port))
            connection_time = (time.time() - start_time) * 1000  # 转换为毫秒
            
            if result == 0:
                print(f"  ✅ TCP连接成功 - 耗时: {connection_time:.1f}ms")
                
                # 发送RTSP OPTIONS请求
                rtsp_request = f"OPTIONS {self.rtsp_url} RTSP/1.0\r\nCSeq: 1\r\n\r\n"
                sock.send(rtsp_request.encode())
                
                # 接收响应
                response = sock.recv(1024).decode()
                sock.close()
                
                if "RTSP/1.0 200 OK" in response:
                    print(f"  ✅ RTSP握手成功")
                    self.results["rtsp_connection_time"].append(connection_time)
                    return connection_time
                else:
                    error_msg = "RTSP握手失败"
                    print(f"  ❌ {error_msg}")
                    self.results["errors"].append(error_msg)
            else:
                error_msg = f"TCP连接失败，错误码: {result}"
                print(f"  ❌ {error_msg}")
                self.results["errors"].append(error_msg)
                
        except Exception as e:
            error_msg = f"RTSP连接测试失败: {str(e)}"
            print(f"  ❌ {error_msg}")
            self.results["errors"].append(error_msg)
        
        return None
    
    def test_stream_with_ffprobe(self):
        """使用ffprobe分析流信息"""
        print(f"🔍 分析RTSP流信息...")
        
        try:
            # 使用ffprobe获取流信息
            cmd = [
                "ffprobe", 
                "-v", "quiet",
                "-print_format", "json",
                "-show_streams",
                "-show_format",
                "-rtsp_transport", "tcp",  # 使用TCP传输
                "-analyzeduration", "2000000",  # 2秒分析时间
                "-probesize", "1000000",
                self.rtsp_url
            ]
            
            start_time = time.time()
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
            analysis_time = (time.time() - start_time) * 1000
            
            if result.returncode == 0:
                stream_info = json.loads(result.stdout)
                
                # 提取关键信息
                format_info = stream_info.get("format", {})
                streams = stream_info.get("streams", [])
                
                print(f"  ✅ 流分析成功 - 耗时: {analysis_time:.1f}ms")
                print(f"    📊 格式: {format_info.get('format_name', 'Unknown')}")
                print(f"    ⏱️  时长: {format_info.get('duration', 'Unknown')}")
                
                for i, stream in enumerate(streams):
                    codec_name = stream.get("codec_name", "Unknown")
                    width = stream.get("width", "N/A")
                    height = stream.get("height", "N/A")
                    fps = stream.get("r_frame_rate", "N/A")
                    
                    print(f"    🎬 流{i}: {codec_name} {width}x{height} {fps}fps")
                
                self.results["stream_info"] = {
                    "analysis_time": analysis_time,
                    "format": format_info,
                    "streams": streams
                }
                
                return True
            else:
                error_msg = f"ffprobe分析失败: {result.stderr}"
                print(f"  ❌ {error_msg}")
                self.results["errors"].append(error_msg)
                
        except subprocess.TimeoutExpired:
            error_msg = "ffprobe分析超时"
            print(f"  ❌ {error_msg}")
            self.results["errors"].append(error_msg)
        except FileNotFoundError:
            error_msg = "未找到ffprobe工具，请安装FFmpeg"
            print(f"  ❌ {error_msg}")
            self.results["errors"].append(error_msg)
        except Exception as e:
            error_msg = f"流分析失败: {str(e)}"
            print(f"  ❌ {error_msg}")
            self.results["errors"].append(error_msg)
        
        return False
    
    def run_comprehensive_test(self):
        """运行综合延迟测试"""
        print("=" * 60)
        print("🔧 RTSP延迟综合诊断工具")
        print(f"📡 目标地址: {self.rtsp_url}")
        print(f"🕐 测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("=" * 60)
        
        # 1. 网络延迟测试
        network_latency = self.test_network_latency()
        
        # 2. RTSP连接测试
        rtsp_connection_time = self.test_rtsp_connection()
        
        # 3. 流信息分析
        stream_analysis_success = self.test_stream_with_ffprobe()
        
        # 生成诊断报告
        self.generate_diagnosis_report(network_latency, rtsp_connection_time, stream_analysis_success)
    
    def generate_diagnosis_report(self, network_latency, rtsp_connection_time, stream_analysis_success):
        """生成诊断报告"""
        print("\n" + "=" * 60)
        print("📋 延迟诊断报告")
        print("=" * 60)
        
        # 网络层诊断
        if network_latency is not None:
            if network_latency < 10:
                print("🟢 网络延迟: 优秀 (<10ms)")
            elif network_latency < 50:
                print("🟡 网络延迟: 良好 (10-50ms)")
            elif network_latency < 100:
                print("🟠 网络延迟: 一般 (50-100ms)")
            else:
                print("🔴 网络延迟: 较差 (>100ms)")
        else:
            print("🔴 网络延迟: 测试失败")
        
        # RTSP连接诊断
        if rtsp_connection_time is not None:
            if rtsp_connection_time < 100:
                print("🟢 RTSP连接: 快速 (<100ms)")
            elif rtsp_connection_time < 500:
                print("🟡 RTSP连接: 正常 (100-500ms)")
            elif rtsp_connection_time < 1000:
                print("🟠 RTSP连接: 较慢 (500-1000ms)")
            else:
                print("🔴 RTSP连接: 很慢 (>1000ms)")
        else:
            print("🔴 RTSP连接: 连接失败")
        
        # 流分析诊断
        if stream_analysis_success:
            print("🟢 RTSP流: 可正常解析")
        else:
            print("🔴 RTSP流: 解析失败或不可用")
        
        # 延迟问题诊断
        print("\n📊 延迟问题诊断:")
        
        if len(self.results["errors"]) == 0:
            print("  ✅ 所有测试通过，延迟主要来源:")
            if network_latency and network_latency > 50:
                print("    🌐 网络延迟较高，可能是网络问题")
            if rtsp_connection_time and rtsp_connection_time > 500:
                print("    📹 RTSP连接较慢，可能是服务器响应问题")
            if network_latency and rtsp_connection_time:
                if rtsp_connection_time > network_latency * 5:
                    print("    📡 推流端响应较慢，建议检查推流服务器")
                else:
                    print("    📱 延迟主要来自网络传输")
        else:
            print("  ❌ 发现以下问题:")
            for error in self.results["errors"]:
                print(f"    - {error}")
        
        # 优化建议
        print("\n💡 优化建议:")
        if network_latency and network_latency > 50:
            print("  - 检查网络连接质量")
            print("  - 尝试使用有线连接替代WiFi")
        
        if not stream_analysis_success:
            print("  - 检查RTSP服务器是否正常运行")
            print("  - 验证RTSP URL是否正确")
            print("  - 检查防火墙设置")
        
        print("  - 在Qt应用中设置更小的缓冲区")
        print("  - 使用TCP传输替代UDP（更稳定但延迟稍高）")
        print("  - 降低视频分辨率和帧率以减少延迟")
        
        print("=" * 60)

def main():
    tester = RTSPLatencyTester()
    tester.run_comprehensive_test()

if __name__ == "__main__":
    main()